/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package econosim;

import java.util.*;
import simframe.simulation.*;


/**
 *
 * @author Steve Noble
 */
public class FreeMarket extends Market {

    
    	// look for offers in market with minimal cost
	// do not purchase if above maxCost
	public void transact(TransActionAgent agent, Offer.Type type, double maxCost, double amt) {
		
	}

    public void processOrders() {

            // purchase orders
          Map<TransActionAgent, Queue<Offer>> agentOfferList = offers.get(Offer.Type.Buy);

         if (agentOfferList == null || agentOfferList.size() == 0 ) {
             return;
        }

        boolean done = false;

        while (!done) {
            done = true;
            for (Queue<Offer> offerList : agentOfferList.values()) {

                if (offerList != null && !offerList.isEmpty()) {
                    Offer offer = offerList.remove();

                    Offer newOffer = processOffer(offer);


                    if (newOffer != null) {
                        offerList.add(newOffer);
                    }
                }
            }
        }

        return;
    }

      private Offer processOffer(Offer purchaseOrder) {

        Map<TransActionAgent, Queue<Offer>> agentSellList = offers.get(Offer.Type.Sell);

        if (agentSellList == null || agentSellList.size() == 0) {
            return null;
        }

       double minCost = Double.MAX_VALUE;
       double minPartialCost =  Double.MAX_VALUE;

       // employ greedy algorithm
       // find first sell order with smallest cost that sells a size bigger then you need

	      Offer selectedOffer = null;
          Offer partialOffer = null;
          for (Queue<Offer> offerList : agentSellList.values()) {
              for (Offer offer : offerList) {
                double cost = offer.getPrice() + fee(purchaseOrder.getAgent(), offer.getAgent());

                  if (offer.getUtility() > purchaseOrder.getUtility()) {
                      if (cost < minCost) {
                          selectedOffer = offer;
                          minCost = cost;
                      }
                  }
                  else {
                       if (cost < minPartialCost) {
                          partialOffer = offer;
                          minPartialCost = cost;
                      }
                  }
              }
          }


	         // complete transaction
          if (selectedOffer != null) {
              return executePurchaseOrder(selectedOffer, purchaseOrder);
          } else if (partialOffer != null) {

              return executePurchaseOrder(partialOffer, purchaseOrder);

          }

        return null;
    }

    @Override
    public void reset() {
       action(processOrders, 18 * Time.Hour);
       action(clearMarket, 23 * Time.Hour);
    }
}